package com.zlyx.easy.core.utils;

import java.util.List;
import java.util.Map;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.Cache;
import org.springframework.cache.Cache.ValueWrapper;
import org.springframework.cache.CacheManager;
import org.springframework.cache.concurrent.ConcurrentMapCache;
import org.springframework.stereotype.Component;

import com.zlyx.easy.core.collections.EasyList;
import com.zlyx.easy.core.collections.Lists;
import com.zlyx.easy.core.config.AppConfig;
import com.zlyx.easy.core.map.EasyMap;
import com.zlyx.easy.core.map.Maps;

/**
 * <p>
 * 缓存操作工具
 * </p>
 *
 * @author 赵光
 * @since 2018年12月5日
 */
@Component
public class CacheUtils {

	private static CacheManager cacheManager;

	private static Cache cache;

	public CacheUtils(@Autowired(required = false) CacheManager cacheManager) {
		CacheUtils.cacheManager = cacheManager;
	}

	public static Cache getCache() {
		if (cache != null) {
			return cache;
		}
		if (cacheManager != null) {
			cache = cacheManager.getCache(AppConfig.getName());
		}
		if (cache == null) {
			cache = new ConcurrentMapCache(AppConfig.getName());
		}
		return cache;
	}

	/**
	 * 缓存类型
	 * 
	 * @return
	 */
	public static String getName() {
		return getCache().getName();
	}

	/**
	 * 添加缓存
	 * 
	 * @param key
	 * @param value
	 */
	public static void put(String key, Object value) {
		getCache().put(key, value);
	}

	/**
	 * 添加缓存
	 * 
	 * @param key
	 * @param value
	 */
	public static void putIfAbsent(String key, Object value) {
		getCache().putIfAbsent(key, value);
	}

	/**
	 * 删除缓存
	 * 
	 * @param <T>
	 * @param key
	 * @return
	 */
	public static <T> T remove(String key) {
		return evict(key);
	}

	/**
	 * 删除缓存
	 * 
	 * @param <T>
	 * @param key
	 * @return
	 */
	public static <T> T evict(String key) {
		T value = get(key);
		getCache().evict(key);
		return value;
	}

	/**
	 * 包含
	 * 
	 * @return
	 */
	public static boolean containsKey(String key) {
		return getCache().get(key) != null;
	}

	/**
	 * 包含
	 * 
	 * @return
	 */
	public static boolean withoutKey(String key) {
		return getCache().get(key) == null;
	}

	/**
	 * 查询缓存
	 * 
	 * @param <T>
	 * @param key
	 * @param type
	 * @return
	 */
	public static <T> T get(String key, Class<T> type) {
		return (T) getCache().get(key, type);
	}

	/**
	 * 查询
	 *
	 * @return
	 */
	@SuppressWarnings("unchecked")
	public static <T> T get(String key) {
		ValueWrapper valueWrapper = getCache().get(key);
		return valueWrapper == null ? null : (T) valueWrapper.get();
	}

	/**
	 * getString
	 * 
	 * @param key
	 * @return
	 */
	public static String getString(String key) {
		String value = get(key);
		return value == null || "".equals(value) ? null : String.valueOf(value);
	}

	/**
	 * getInt
	 * 
	 * @param key
	 * @return
	 */
	public static Integer getInt(String key) {
		return Integer.parseInt(getString(key));
	}

	/**
	 * getLong
	 * 
	 * @param key
	 * @return
	 */
	public static Long getLong(String key) {
		return Long.parseLong(getString(key));
	}

	/**
	 * getMap
	 * 
	 * @param key
	 * @return
	 * @throws Exception
	 */
	@SuppressWarnings("unchecked")
	public <K, V> EasyMap<K, V> getMap(String key) throws Exception {
		Object value = get(key);
		if (value == null) {
			return null;
		}
		if (Map.class.isAssignableFrom(value.getClass())) {
			return Maps.newMap((Map<K, V>) value);
		}
		return JsonUtils.toMap(JsonUtils.toJson(value));
	}

	/**
	 * getList
	 * 
	 * @param <T>
	 * @param key
	 * @return
	 * @throws Exception
	 */
	@SuppressWarnings("unchecked")
	public <T> EasyList<T> getList(String key) throws Exception {
		Object value = get(key);
		if (value == null) {
			return null;
		}
		if (List.class.isAssignableFrom(value.getClass())) {
			return Lists.newList((List<T>) value);
		}
		return JsonUtils.toList(JsonUtils.toJson(value));
	}

	/**
	 * 清空缓存
	 * 
	 * @return
	 */
	public static void clear() {
		getCache().clear();
	}

}
